use crate::views::{CommentList, TaskList};
use log::trace;
use yew::prelude::*;
use yew_store::StoreLink;

use crate::state::{Action, Comment, Event, State, Task};

use crate::service::{self, FetchTask};
use failure::Error;

pub struct Model {
    store: StoreLink<State, Action>,
    link: ComponentLink<Self>,
    fetch_task: Option<FetchTask>,
    message: Option<String>,
}

pub enum Msg {
    StoreEvent(Event),
    FetchTask,
    FetchTaskDone(Result<Vec<Task>, Error>),
    FetchComment(i32),
    FetchCommentDone(Result<Vec<Comment>, Error>),
}

#[derive(Properties)]
pub struct Props {
    #[props(required)]
    pub store: StoreLink<State, Action>,
}

impl Component for Model {
    type Message = Msg;
    type Properties = Props;

    fn create(props: Self::Properties, mut link: ComponentLink<Self>) -> Self {
        let callback = link.send_back(|event| Msg::StoreEvent(event));
        Model {
            store: props.store.reform(Some(callback)),
            link: link,
            fetch_task: None,
            message: None,
        }
    }

    fn mounted(&mut self) -> ShouldRender {
        self.update(Msg::FetchTask);
        false
    }

    fn update(&mut self, msg: Self::Message) -> ShouldRender {
        match msg {
            Msg::StoreEvent(event) => return self.handle(event),
            Msg::FetchTask => {
                self.fetch_task =
                    service::fetch_all_task(self.link.send_back(|resp| Msg::FetchTaskDone(resp)));
                false
            }
            Msg::FetchTaskDone(resp) => {
                // trace!("{:?}", resp);
                resp.map(|tasks| self.store.send(Action::SetTasks(tasks)))
                    .unwrap_or_else(|err| self.message = Some(err.to_string()));
                true
            }
            Msg::FetchComment(tid) => {
                self.fetch_task = service::fetch_all_comments(
                    tid,
                    self.link.send_back(|resp| Msg::FetchCommentDone(resp)),
                );
                false
            }
            Msg::FetchCommentDone(resp) => {
                // trace!("{:?}", resp);
                resp.map(|comments| self.store.send(Action::SetComments(comments)))
                    .unwrap_or_else(|err| self.message = Some(err.to_string()));
                true
            }
        }
    }
}
impl Model {
    fn handle(&mut self, event: Event) -> ShouldRender {
        trace!("{:?}", event);
        false
    }
}

impl Renderable<Model> for Model {
    fn view(&self) -> Html<Self> {
        html! {
            <>
            <nav class="flex fixed w-screen items-center justify-start p-2 bg-gray-400">
                <div class="mr-6">
                    <a class="text-blue-500 hover:text-blue-800">
                        <img class="h-12" src="images/logo2.png"/>
                    </a>
                </div>
                <div class="mr-6">
                    <a class="text-blue-500 hover:text-blue-800">
                         {"所有日志("}{self.store.state().tasks_number}{")"}
                    </a>
                </div>
                <div class="mr-6">
                    <a class="text-blue-500 hover:text-blue-800">
                         {"已完成 "}
                    </a>
                </div>
                <div class="mr-6">
                    <a class="text-blue-500 hover:text-blue-800">
                        {"时间线"}
                    </a>
                </div>
            </nav>
            <section class="flex min-h-screen max-h-screen pt-16">
                <div class="w-3/5 border-r-2 p-4 min-h-full max-h-full overflow-y-scroll">
                    <TaskList store=self.store.clone() on_item_click=|tid| Msg::FetchComment(tid) />
                </div>
                <div class="w-2/5 p-4 min-h-full max-h-full overflow-y-scroll">
                    <CommentList store=self.store.clone() />
                </div>
            </section>
            </>
        }
    }
}
